﻿<!-- 修改于2024-05-17，添加company-select showOffice属性 -->
<!-- 修改于2024-04-03，解决updateValue调用两次问题 -->
<style scoped>
.form-label-break /deep/ .el-form-item__label{
  line-height:20px;
  margin-top:0px
}
</style>
<template>
<!--  <el-row v-if="!isLoading" type="flex" style="flex-wrap: wrap;">-->
  <div>
    <el-row v-for="(subList,index) in fieldRowList">

      <el-col v-for="field in subList" :span="field.colSpan?field.colSpan:24/columns" :key="timestamp+'_col_'+field.id">
        <el-form-item :ref="'style'+ field.id" v-if="!field.isHide(fieldValueMap)"
                      :label="field.name?field.name+':':''"
                      :prop="field[dataKey]" :rules="field.rules">
            <span slot="label" style="display:inline-block;">
            {{field.name?field.name+':':''}}
            <el-tooltip v-if="field.tooltip" effect="dark" :content="field.tooltip" placement="bottom">
              <i class='el-icon-question' />
            </el-tooltip>
          </span>
          <el-input v-if="field.component.id=='textarea'" type="textarea" v-model="fieldValueMap[field[dataKey]]"
                    @change="updateValue(field)" autocomplete="off" :placeholder="field.component.placeholder?field.component.placeholder:'请输入内容'"
                    :readonly="readonly"
                    :maxlength="field.component.maxLength?field.component.maxLength:1000"
                    :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"
          />
          <input-number-range v-else-if="field.component.id=='input-number-range'"
                              v-model="fieldValueMap[field[dataKey]]"
                              @input="updateValue(field)"
                              :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"
                              :precision="field.component.precision?field.component.precision:0"></input-number-range>
          <meta-select v-else-if="field.component.id=='meta-select'"
                       :key="'form_item_'+field.index+'_'+field.id+timestamp"
                       :parent="fieldValueMap[field.parent]"
                       :placeholder="field.component.placeholder"
                       :clearable="field.component.clearable"
                       v-model="fieldValueMap[field[dataKey]]"
                       @change="updateValue(field)"
                       :default-select="field.component.defaultSelect"
                       :before-display-list="field.component.load"
                       :value-key="field.component.valueKey?field.component.valueKey:'id'"
                       :type="field.component.type" :readonly="readonly||field.readonly||field.isReadonly(fieldValueMap)"
                       :multiple="field.component.multiple==true"
                       :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"></meta-select>
          <meta-radio v-else-if="field.component.id=='meta-radio'"
                       :parent="fieldValueMap[field.parent]"
                       :placeholder="field.component.placeholder"
                       v-model="fieldValueMap[field[dataKey]]"
                       @change="updateValue(field)"
                       :default-select="field.component.defaultSelect"
                       :type="field.component.type" :readonly="readonly||field.readonly||field.isReadonly(fieldValueMap)"
                       :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"></meta-radio>
          <dict-value-select v-else-if="field.component.id=='dict-value-select'" :parent="field.component.type"
                             :key="'form_item_'+field.index+'_'+field.id+timestamp"
                             v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
                             :readonly="readonly||field.readonly||field.isReadonly(fieldValueMap)" :multiple="field.component.multiple==true"
                             :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"></dict-value-select>
          <data-select v-else-if="field.component.id=='data-select'"
                       :key="'form_item_'+field.index+'_'+field.id+timestamp"
                       :disabled="field.component.disabled||field.isDisabled(fieldValueMap)||(field.parent&&!fieldValueMap[field.parent])"
                       :parent="fieldValueMap[field.parent]"
                       :param-data="fieldValueMap"
                       :default-select="field.component.defaultSelect"
                       :request-method="field.component.requestMethod?field.component.requestMethod:'get'"
                       :value-key="field.component.valueKey?field.component.valueKey:'id'"
                       :data-url="field.component.getDataUrl?field.component.getDataUrl(fieldValueMap):null"
                       @load="(dataList)=>{loadCallback(dataList,data,field)}"
                       :data="field.component.data"  v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
                       :readonly="readonly||field.component.readonly||field.isReadonly(fieldValueMap)" :multiple="field.component.multiple==true"></data-select>
          <company-select v-else-if="field.component.id=='company-select'" :hide-root="field.component.hideRoot"  v-model="fieldValueMap[field[dataKey]]"
                          :placeholder="field.component.placeholder"
                          :value-key="field.component.valueKey?field.component.valueKey:'id'"
                          :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"
                          :checkStrictly="field.component.checkStrictly==false?false:true"
                          :multiple="field.component.multiple==true"
                          :show-office="field.component.showOffice"
                          @load="(dataList)=>{loadCallback(dataList,fieldValueMap,field)}"
                          @change="updateValue(field)"  :readonly="readonly||field.component.readonly||field.isReadonly(fieldValueMap)"></company-select>
          <el-select v-else-if="field.component.id=='select'"  v-model="fieldValueMap[field[dataKey]]"
                     @change="updateValue(field)"  autocomplete="off" :placeholder="field.component.placeholder?field.component.placeholder:'请选择'"
                     filterable clearable :readonly="readonly||field.component.readonly||field.isReadonly(fieldValueMap)"
                     :multiple="field.component.multiple==true" :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)">
            <el-option v-for="item in field.component.optionList" :label="item.name" :value="item.id" :key="timestamp+'_'+field.id+'_'+item.id">
            </el-option>
          </el-select>
          <el-date-picker
              v-else-if="field.component.id=='year-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              :placeholder="field.component.placeholder?field.component.placeholder:''"
              type="year"
              format="yyyy"
              value-format="yyyy"
              :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"
          />
          <el-date-picker
              v-else-if="field.component.id=='month-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              type="month"
              :format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM'"
              :value-format="field.component.format&&field.component.format.length>0?field.component.format:'yyyyMM'"
              :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"/>
          <el-date-picker
              v-else-if="field.component.id=='monthrange-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              type="monthrange"
              range-separator="至"
              start-placeholder="开始月份"
              end-placeholder="结束月份"
              :format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM'"
              :value-format="field.component.format&&field.component.format.length>0?field.component.format:'yyyyMM'"
              :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"/>

          <el-date-picker
              v-else-if="field.component.id=='date-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              type="date"
              :format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM-dd'"
              :value-format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM-dd'"
              :disabled="field.disabled==true||field.isDisabled(fieldValueMap)"
          />
          <el-date-picker
              v-else-if="field.component.id=='datetime-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              type="datetime"
              :format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM-dd HH:mm:ss'"
              :value-format="field.component.format&&field.component.format.length>0?field.component.format:'yyyy-MM-dd HH:mm:ss'"
              :disabled="field.disabled==true||field.isDisabled(fieldValueMap)"
          />
          <icon-picker
              v-else-if="field.component.id=='icon-picker'"
              v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
              :disabled="field.disabled==true||field.isDisabled(fieldValueMap)"
          />
          <el-radio-group v-else-if="field.component.id=='radio'" v-model="fieldValueMap[field[dataKey]]"
                          :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)"
                          @change="updateValue(field)"
                          :readonly="readonly">
            <template v-if="field.component.optionList">
              <el-radio v-for="option in field.component.optionList" :key="timestamp+'_option_'+field.id+option.id" :label="option.id">{{ option.name }}</el-radio>
            </template>
            <!-- 不设置选项列表默认只有是否 -->
            <template v-if="!field.component.optionList">
              <el-radio :label="true">是</el-radio>
              <el-radio :label="false">否</el-radio>
            </template>
          </el-radio-group>
<!--          <el-date-picker-->
<!--              v-else-if="field.displayConfig.component=='datepicker'"-->
<!--              v-model="fieldValueMap[field[dataKey]]"-->
<!--              type="date"-->
<!--              :format="field.displayConfig.format&&field.displayConfig.format.length>0?field.displayConfig.format:'yyyy-MM-dd'"-->
<!--              :value-format="field.displayConfig.format&&field.displayConfig.format.length>0?field.displayConfig.format:'yyyy-MM-dd'"-->
<!--          />-->
          <el-input v-else-if="field.component.id=='password'" type="password" v-model="fieldValueMap[field[dataKey]]"
                    @change="updateValue(field)" autocomplete="off"
                    :placeholder="field.component.placeholder?field.component.placeholder:'请输入密码'" :readonly="readonly||field.component.readonly" clearable
                    :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)">
          </el-input>
          <el-input v-else v-model="fieldValueMap[field[dataKey]]" @change="updateValue(field)"
                    autocomplete="off"
                    :placeholder="field.component.placeholder?field.component.placeholder:'请输入内容'" :readonly="readonly" clearable
                    :disabled="field.component.disabled==true||field.isDisabled(fieldValueMap)" >
            <template v-if="field.unit&&field.unit.length>0&& unitNameMap[field.unit] != '无'"
                      slot="append">{{unitNameMap[field.unit]?unitNameMap[field.unit]:field.unit}}</template>
          </el-input>
        </el-form-item>
      </el-col>
      <slot v-if="index==fieldRowList.length-1"></slot>
    </el-row>
  </div>

</template>
<script>
/**
 * 自定义字段数据展示、编辑组件
 */
function noop() {return false;}
export default {
  name: "CustomFieldFormItem",
  // props:{
  //   title: {},action:{},headers:{},data:{},name:{},showFileList:{type:Array,default:false}
  //   ,accept:{},'on-preview':{},'on-remove':{},fileList:{type:Array,default:()=>{return []}}
  // },
  props: {
    //自定义表id，用于加载后端数据
    tableId: {type:String,default:null},
    //默认列数
    columns:{type:Number,default: 1},
    //字段数据
    data:{},
    //主键字段
    dataKey:{
      type:String,
      default:'id'
    },
    //字段列表
    fields: {},
    //是否只读
    readonly:{type:Boolean,default:false},
    //作用域
    scope:{type:String,default:null}
  },

    data(){
      return {
        //字段值集合
        fieldValueMap:{},
        //字段列表
        fieldList:[],
        fieldRowList:[],
        //加载状态
        isLoading:true,
        //数据单位名称集合
        unitNameMap:{},
        // optionMap:{},
        timestamp:new Date().getTime()
      }
    },
  computed:{

  },
  watch: {
    data: {
      handler(val,oldVal) {
        this.fieldValueMap = this.initFieldValueMap(this.fieldList);
        this.fieldRowList = this.generateFieldRowList(this.fieldList);
        this.$emit('load-field-success', this.fieldList, this.fieldValueMap);
      },
      deep:true,
    },
    fields: {
      handler(val, oldVal) {
        this.loadInputFieldList();
      },
      deep: true
    },
    scope(newValue){
      this.loadInputFieldList();
    },
    tableId( ){
      this.loadInputFieldList();
    },
  },
  mounted(){
    this.loadInputFieldList();
    this.loadMetaNameMap('unit-type',map=>{
      this.unitNameMap = map;
    });
    this.$nextTick(() =>{
      // 处理折行显示问题 如果元素的高度大于元素内输入框的高度则进行折行处理
      for (let subList of this.fieldRowList) {
        for (let item of subList){
          let style = this.$refs['style'+item.id][0];
          // 获取元素（名称的高度）
          let labelHeight =  style.$el.clientHeight;
         let inputHeight = 0;
         // 获取输入框的高度
          for (let child of style.$children) {
            if (child.$el.className == 'el-radio-group') {
              inputHeight = child.$el.clientHeight * 3;
            } else {
              inputHeight = child.$el.clientHeight * 1.5;
            }
          }
          if (labelHeight > inputHeight) {
            style.$el.classList.add('form-label-break')
          }
        }
      }

    })
  },
  methods: {
    loadInputFieldList: function () {
      if((!this.fields||this.fields.length<=0)&&!this.tableId) {
        this.$message.warning("未配置字段列表或表id，无法展示")
        return;
      }
      this.isLoading = true;
      if(this.fields&&this.fields.length>0){
        this.initFieldList(this.fields);
        this.isLoading = false;
      } else {
        this.$get("/field/data?tableId=" + this.tableId, {scope: this.scope}, (response) => {
          this.initFieldList(response.data);
        }, () => {
          this.isLoading = false;
        });
      }
    },
    //初始化字段列表。兼容两种方式，一种后端获取，带displayConfig，另一种直接配置，结构更简单，无displayConfig
    initFieldList(dataList) {
      let list = [];
      // for(const item of dataList) {
      //   if(item.show) {
      //     if(item.displayConfig&&item.displayConfig.component=='select'&&item.displayConfig.optionType){
      //       this.optionMap[item.displayConfig.optionType] = [];
      //     }
      //   }
      // }
      // this.optionMap = JSON.parse(JSON.stringify(this.optionMap));

      for(const sourceItem of dataList) {
        //删除show字段
        // if(!sourceItem.show) {
        //   continue;
        // }
        let item = JSON.parse(JSON.stringify(sourceItem))
        item.index = list.length;
        if(!sourceItem.isDisabled) {
          //判断是否禁用函数默认为false
          item.isDisabled = noop;
        } else {
          item.isDisabled = sourceItem.isDisabled;
        }
        if(!sourceItem.isReadonly) {
          //判断是否需要禁用
          item.isReadonly = noop;
        } else {
          item.isReadonly = sourceItem.isReadonly;
        }
        if(!sourceItem.isHide) {
          //判断是否需要隐藏
          item.isHide = noop;
          if(sourceItem.hide) {
            //如果配置hide属性为true，也隐藏
            item.isHide = ()=>{return true;};
          } else if(sourceItem.show==false) {
            //兼容以前字段
            item.isHide = ()=>{return true;};
          }
        } else {
          item.isHide = sourceItem.isHide;
        }

        //组件配置,兼容简便写法，简便写法component直接设置组件名称
        let componentConfig = null;
        if(typeof item.component == 'string') {
          componentConfig = {id:item.component?item.component:'input'};
          if(item.dataUrl){
            componentConfig.dataUrl = item.dataUrl;
          }
          if(item.type) {
            componentConfig.type = item.type;
          }
        } else if(item.component) {
          componentConfig = item.component;
          if(sourceItem.component.change) {
            //函数无法复制，手动指定
            item.component.change = sourceItem.component.change;
          }
        } else {
          //默认为input
          componentConfig = {id:'input'};
        }
        if(item.multiple) {
          componentConfig.multiple = item.multiple;
        }
        if(item.readonly) {
          componentConfig.readonly = item.readonly;
        }
        if(item.disabled) {
          componentConfig.disabled = item.disabled;
        }
        if(item.data) {
          componentConfig.data = item.data;
        }

        if(item.displayConfig) {
          //兼容后端数据结构
          if(item.displayConfig.component) {
            componentConfig.id = item.displayConfig.component;
          }
          if(item.displayConfig&&item.displayConfig.component=='select'&&item.displayConfig.optionType){
            if(item.displayConfig.optionSource=='enum') {
              componentConfig.id = 'meta-select';
              componentConfig.type=item.displayConfig.optionType;
              // let optionType1 = item.displayConfig.optionType;
              // this.$get('/meta/type/'+item.displayConfig.optionType,{},(response)=>{
              //   this.optionMap[optionType1] = response.data;
              // })
            } else if(item.displayConfig.optionSource=='dict') {
              componentConfig.id = "dict-value-select";
              componentConfig.type=item.displayConfig.optionType;
              // let optionType2 = item.displayConfig.optionType;
              // this.$get('/dict/queryList',{type:optionType2},(response2)=>{
              //   this.optionMap[optionType2] = response2.data;
              // })
            } else if(item.displayConfig.optionSource=='custom'&&item.displayConfig.optionType) {
              componentConfig.id = "data-select";
              componentConfig.dataUrl=item.displayConfig.optionType;
              // let optionType3 = item.displayConfig.optionType;
              // this.$get(optionType3,{},(response)=>{
              //   this.optionMap[optionType3] = response.data;
              // })
            } else if(item.displayConfig.optionSource=='static'&&item.displayConfig.optionType) {
              componentConfig.id = "data-select";
              try{
                componentConfig.data=eval(item.displayConfig.optionType);
              } catch (e) {
                console.error('选择框静态数据配置错误',item,e);
                componentConfig.data=[];
              }
              // let optionType3 = item.displayConfig.optionType;
              // this.$get(optionType3,{},(response)=>{
              //   this.optionMap[optionType3] = response.data;
              // })
            }
            if(item.displayConfig.defaultSelect) {
              item.defaultSelect = item.displayConfig.defaultSelect;
            }

          }
          if(sourceItem.displayConfig.change) {
            componentConfig.change = sourceItem.displayConfig.change;
          }
          //所占宽度
          if(item.displayConfig.colSpan) {
            item.colSpan = item.displayConfig.colSpan;
          }
          if(item.displayConfig.name) {
            //展示名称
            item.name = item.displayConfig.name;
          }
          //最大长度
          item.maxLength = item.displayConfig.maxLength;
        }
        item.component = componentConfig;
        //处理dataUrl参数
        if(item.component.id=='data-select') {
          if (item.component.dataUrl) {
            //注意，此处必须用let
            let dataUrl = item.component.dataUrl;
            let parent = item.parent;
            let id = item.id;
            item.component.getDataUrl = (data) => {
              //此处不可用item.component.dataUrl.repleace,否则获取为undefined
                return dataUrl.replace('${parent}', data[parent])
                    .replace('${id}', data[id]);
            };
          } else if (sourceItem.component) {
            item.component.getDataUrl = sourceItem.component.getDataUrl;
          }
        }
        if(sourceItem.component&&sourceItem.component.load) {
          //load回调函数
          item.component.load = sourceItem.component.load;
        }
        list.push(item);
      }
      this.fieldValueMap = this.initFieldValueMap(list);
      this.fieldList = list;
      this.fieldRowList = this.generateFieldRowList(list);
      this.$emit('load-field-success',this.fieldList,this.fieldValueMap);
    },
    //将字段进行分行处理
    generateFieldRowList(list) {
      let rowList = [];
      let spanCount = 0;
      let subList = [];
      for(let item of list) {
        if(item.isHide&&item.isHide(this.fieldValueMap)) {
          //如果是隐藏字段，直接忽略
          continue;
        }
        let span = item.colSpan?item.colSpan:24/this.columns;
        spanCount+=span;
        if(spanCount>24) {
          rowList.push(subList);
          subList = [];
          spanCount = span;
        }
        subList.push(item);
      }

      if(subList.length>0) {
        rowList.push(subList);
      }
      return rowList;
    },
    //初始化数据
    initFieldValueMap(fieldList) {
      let map = {};
      for(let item of fieldList) {
        if(this.data&&this.data[item[this.dataKey]]==undefined) {
          this.data[item[this.dataKey]] = '';
          if(item.dataType&&item.dataType=='array') {
            this.data[item[this.dataKey]] = [];
          }
          if(item.defaultValue!=undefined||item.getDefaultValue) {
            if(item.getDefaultValue) {
              this.data[item[this.dataKey]] = item.getDefaultValue();
            } else {
              //不可用item.defaultValue 进行判断，默认值有可能为false或空串
              this.data[item[this.dataKey]] = item.defaultValue;
            }
          }
        }
        if(item.component&&(item.component=='year-picker'||item.component.id=='year-picker')){
          //如果是年份选择框，赋值数字会报错，转换为字符串
          this.data[item[this.dataKey]] = this.data[item[this.dataKey]]+'';
        }
        map[item[this.dataKey]] = this.data[item[this.dataKey]];
      }
      //补全原始数据中新数据不存在的key值
      for(let key in this.data) {
        if(map[key]==undefined) {
          map[key] = this.data[key];
        }
      }
      return map;
    },
    updateValue(field){
      let fieldId = field[this.dataKey];
      if(this.data[fieldId] == this.fieldValueMap[fieldId]) {
        return;
      }
      this.data[fieldId] = this.fieldValueMap[fieldId];
      if(field.component.change) {
        //如果字段定义组件change事件，则回调该函数
        field.component.change(this.fieldValueMap[fieldId],this.data);
      }
    },
    //加载数据回调
    loadCallback(dataList,fieldData,field) {
      if(!field.component.load) {
        return;
      }
      field.component.load(dataList,fieldData);
    }
  }
};
</script>
